/**
 * @author phoenics@126com
 * @date 2017年10月9日 上午10:51:59
 * @version V1.0
 */

package phoenics.nlp.ml.classify;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 朴素贝叶斯文本分类java实现
 */
public class NativeBayes {
	private static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(NativeBayes.class);
	 /**
     * 默认频率
     */
    private double defaultFreq = 0.1;
    private Map<String, List<String>> files_test = new HashMap<>();
    
    
    
    private Map<String, Double> classFeaProb = new HashMap<>();
    private Map<String, Double> classDefaultProb = new HashMap<>();
    
    /**
     * 特征总数
     */
    private Set<String> wordDict = new HashSet<>();
    /**
     *  计算准确率
     * @param reallist 真实类别
     * @param pridlist 预测类别
     */
    public double Evaluate(List<String> reallist, List<String> pridlist){
    	double correctNum = 0.0D;
        for (int i = 0; i < reallist.size(); i++) {
            if(reallist.get(i) .equals(pridlist.get(i))){
                correctNum += 1D;
            }
        }
        double accuracy = correctNum / (double)reallist.size();
        System.out.println("准确率为：" + accuracy);
        return accuracy;
        //System.out.println("准确率为：" + accuracy);
    }
    
    /**
     * 计算精确率和召回率
     * @param reallist
     * @param pridlist
     * @param classname
     */
    public void CalPreRec(List<String> reallist, List<String> pridlist, String classname) {
    	double correctNum = 0.0D;
        double allNum = 0.0D;//测试数据中，某个分类的文章总数
        double preNum = 0.0D;//测试数据中，预测为该分类的文章总数
        for (int i = 0; i < reallist.size(); i++) {
        	if(classname.equals(reallist.get(i))) {
        		 allNum += 1D;
        		 if(reallist.get(i) .equals(pridlist.get(i))){
                     correctNum += 1D;
                 }
        	}
        	if(classname.equals(pridlist.get(i))) {
        		preNum += 1D;
        	}
        }
        System.out.println(classname + " 精确率(跟预测分类比较):" + correctNum / preNum + " 召回率（跟真实分类比较）:" + correctNum / allNum);
    }
    /**
     * 用模型进行预测
     */
    @SuppressWarnings("resource")
	public void PredictTestData() {
    	List<String> reallist=new ArrayList<String>();
        List<String> pridlist=new ArrayList<String>();
        for(String realclassname:files_test.keySet()) {
        	List<String> files =files_test.get(realclassname);
        	for (String file : files) {
        		reallist.add(realclassname);
        		List<String> classnamelist=new ArrayList<String>();
                List<Double> scorelist=new ArrayList<Double>();
                for( String classname :classFeaProb.keySet() ) {
                	//先验概率
                	Double score = Math.log(classFeaProb.get(classname));
                	String[] words =null;
                	try {
						words=new BufferedReader(new FileReader(file)).lines().collect(Collectors.joining()).split(" ");
					} catch (FileNotFoundException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
                	for (String word : words) {
                		if(!wordDict.contains(word)){
                            continue;
                        }
                		/*if(classFeaProb.get(classname).containsKey(word)){
                			score += Math.log(classFeaProb.get(classname).get(word));
                		}else{
                            score += Math.log(classDefaultProb.get(classname));
                        }*/
                	}
                	 classnamelist.add(classname);
                     scorelist.add(score);
                }
                Double maxProb = Collections.max(scorelist);
                int idx = scorelist.indexOf(maxProb);
                pridlist.add(classnamelist.get(idx));
        	}
        }
    }
}







































